home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / COMMON / udp.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  6KB  |  300 lines

  1. /* --------------------------------- udp.c ---------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Handler for server based UDP level networking (low level).
  8.  * An address here is IP address (4 bytes) + UDP port num (2 bytes).
  9.  *
  10.  * It needs the server fly8udp for operation, it will NOT talk directly
  11.  * to another fly8.
  12. */
  13.  
  14. #include "fly.h"
  15.  
  16. #ifdef HAVE_UDP
  17.  
  18. #define PHDATA        pack->raw
  19. #include "fly8udp.h"
  20.  
  21.  
  22. typedef struct port PORT;
  23. struct port {
  24.     int        flags;
  25. #define POF_ON        0x0001
  26.     int        fd;
  27.     struct sockaddr_in    svr, cli;
  28.     int        netport;        /* back-pointer */
  29.     char        *server;        /* server name */
  30.     Uchar        address[LADDRESS];    /* my address */
  31. };
  32.  
  33. static PORT    FAR ports[] = {
  34.     {0, -1},
  35.     {0, -1},
  36.     {0, -1},
  37.     {0, -1},
  38. };
  39. #define    NDEV    rangeof(ports)
  40.  
  41. static int    nports = 0;        /* number of active ports */
  42.  
  43. LOCAL_FUNC int NEAR
  44. UdpOptions (PORT *port, char *options)
  45. {
  46.     char    *p;
  47.     long    l;
  48.  
  49.     if (T(p = get_piarg (options, 0)))
  50.         port->server = p;
  51.     else
  52.         return (1);
  53.  
  54.     if (get_narg (options, "port=", &l))
  55.         l = IPPORT_FLY8;
  56.     port->svr.sin_port = htons ((Ushort)l);
  57.  
  58.     return (0);
  59. }
  60.  
  61. LOCAL_FUNC int FAR
  62. UdpInit (NETPORT *np, char *options)
  63. {
  64.     int        portno;
  65.     PORT        *port;
  66.     char        *protoname;
  67.     struct protoent    *proto;
  68.     struct hostent    *hostptr;
  69.     Ulong        srv_addr;        /* server address */
  70.     int        n;
  71.  
  72.     portno = np->unit-'1';
  73.     if (portno < 0 || portno >= NDEV) {
  74.         MsgEPrintf (-100, "%s.%c: bad port",
  75.             np->NetDriver->name, np->unit);
  76.         return (1);
  77.     }
  78.     port = &ports[portno];
  79.     if (port->flags & POF_ON) {
  80.         MsgEPrintf (-100, "%s.%c: already on",
  81.             np->NetDriver->name, np->unit);
  82.         return (1);
  83.     }
  84.  
  85.     memset (&port->svr, 0, sizeof (port->svr));
  86.     memset (&port->cli, 0, sizeof (port->cli));
  87.  
  88.     if (UdpOptions (port, options))
  89.         return (1);
  90. #ifdef MSDOS
  91.     sock_init ();
  92.  
  93.     if ((port->fd = socket (AF_INET, SOCK_FLY8, IPPROTO_UDP)) < 0) {
  94. #else
  95.     protoname = "udp";
  96.     if ((proto = getprotobyname (protoname)) == NULL) {
  97.         MsgEPrintf (-100, "%s.%c: getprotobyname(%s) failed: %s",
  98.             np->NetDriver->name, np->unit,
  99.             protoname, strerror (errno));
  100.         return (1);
  101.     }
  102.  
  103.     if ((port->fd = socket (AF_INET, SOCK_FLY8, proto->p_proto)) < 0) {
  104. #endif
  105.         MsgEPrintf (-100, "%s.%c: socket() failed: %s",
  106.             np->NetDriver->name, np->unit, strerror (errno));
  107.         return (1);
  108.     }
  109.  
  110. #ifndef MSDOS
  111.     n = fcntl (port->fd, F_GETFL);
  112.     if (fcntl (port->fd, F_SETFL, n|FLY8_NONBLOCK) < 0) {
  113.         MsgEPrintf (-100, "%s.%c: fcntl() failed: %s",
  114.             np->NetDriver->name, np->unit, strerror (errno));
  115.         return (1);
  116.     }
  117. #endif
  118.  
  119. /* Set up server (our output) address.
  120. */
  121.     if ((hostptr = gethostbyname (port->server)) == NULL) {
  122.         MsgEPrintf (-100, "%s.%c: gethostbyname(%s) failed: %s",
  123.             np->NetDriver->name, np->unit,
  124.             port->server, strerror (errno));
  125.         return (1);
  126.     }
  127.  
  128.     if (hostptr->h_addrtype != AF_INET) {
  129.         MsgEPrintf (-100, "%s.%c: not AF_INET address",
  130.             np->NetDriver->name, np->unit);
  131.         return (1);
  132.     }
  133.  
  134.     srv_addr = ((struct in_addr *)hostptr->h_addr_list[0])->s_addr;
  135.     MsgPrintf (-100, "%s.%c: server is %08lx",
  136.             np->NetDriver->name, np->unit, ntohl (srv_addr));
  137.  
  138.     port->svr.sin_family      = AF_INET;
  139.     port->svr.sin_addr.s_addr = srv_addr;
  140.  
  141. /* Set up client (our input) address.
  142. */
  143.     port->cli.sin_family      = AF_INET;
  144.     port->cli.sin_addr.s_addr = htonl (INADDR_ANY);
  145.     port->cli.sin_port        = htons (0);
  146.  
  147.     if (bind (port->fd, (struct sockaddr *) &port->cli,
  148.                         sizeof (port->cli)) < 0) {
  149.         MsgEPrintf (-100, "%s.%c: bind() failed: %s",
  150.             np->NetDriver->name, np->unit,     strerror (errno));
  151.         return (1);
  152.     }
  153.     memcpy (port->address,   (char *)&port->cli.sin_addr.s_addr, 4);
  154.     memcpy (port->address+4, (char *)&port->cli.sin_port,        2);
  155.  
  156.     port->flags |= POF_ON;
  157.     port->netport = np->netport;
  158.     ++nports;
  159.  
  160.     return (0);
  161. }
  162.  
  163. LOCAL_FUNC void FAR
  164. UdpTerm (NETPORT *np)
  165. {
  166.     int    portno;
  167.     PORT    *port;
  168.  
  169.     portno = np->unit-'1';
  170.     if (portno < 0 || portno >= NDEV)
  171.         return;
  172.     port = &ports[portno];
  173.     if (!(port->flags & POF_ON))
  174.         return;
  175.  
  176.     port->server = STRfree (port->server);
  177.     if (port->fd >= 0) {
  178. #ifdef WATTCP
  179.         n_close (port->fd);
  180. #else
  181.         close (port->fd);
  182. #endif
  183.         port->fd = -1;
  184.     }
  185.     port->flags = 0;
  186.     --nports;
  187. }
  188.  
  189. LOCAL_FUNC int FAR
  190. UdpSend (NETPORT *np, PACKET *pack)
  191. {
  192.     int    portno;
  193.     PORT    *port;
  194.     int    n;
  195.  
  196.     if (0 == pack)
  197.         return (0);
  198.  
  199.     portno = np->unit-'1';
  200.     if (portno < 0 || portno >= NDEV)
  201.         return (1);
  202.     port = &ports[portno];
  203.     if (!(port->flags & POF_ON))
  204.         return (1);
  205.  
  206.     if (pack->address) {
  207.         memcpy (PHTO, pack->address, LADDRESS);    /* to */
  208.         pack->address = 0;            /* private */
  209.     } else
  210.         memset (PHTO, 0xff, LADDRESS);        /* broadcast */
  211.     memcpy (PHFROM, port->address, LADDRESS);    /* from */
  212.     PHLEN[0] = (Uchar)(0x0ff&(pack->length >> 8));    /* length */
  213.     PHLEN[1] = (Uchar)(0x0ff&(pack->length));
  214.  
  215.     n = PHSIZE + pack->length;
  216.     if (n != sendto (port->fd, PHEAD, n, 0, (struct sockaddr *)&port->svr,
  217.                             sizeof (port->svr))) {
  218. #ifndef MSDOS
  219.         if (EWOULDBLOCK == errno)
  220.             return (1);    /* busy */
  221.         else
  222. #endif
  223.             return (1);    /* error */
  224.     }
  225.  
  226.     return (0);
  227. }
  228.  
  229. static Uchar    FAR msg[1500];        /* message buffer */
  230.  
  231. LOCAL_FUNC int FAR
  232. UdpReceive (NETPORT *np)
  233. {
  234.     int    portno;
  235.     PORT    *port;
  236.     PACKET    *pack = NULL;
  237.     int    n, len, limit;
  238.  
  239.     portno = np->unit-'1';
  240.     if (portno < 0 || portno >= NDEV)
  241.         return (1);
  242.     port = &ports[portno];
  243.     if (!(port->flags & POF_ON))
  244.         return (1);
  245.  
  246.     for (limit = 256; limit-- > 0;) {
  247.         len = sizeof (struct sockaddr);
  248.         n = recvfrom (port->fd, (char *)msg, sizeof (msg), 0,
  249.                 (struct sockaddr *)&port->cli, &len);
  250.         if (n < 0) {
  251. #ifndef MSDOS
  252.             if (EWOULDBLOCK != errno)
  253. #endif
  254.             {
  255.                 MsgEPrintf (5, "%s.%c: recvfrom() failed: %s",
  256.                     np->NetDriver->name, np->unit,
  257.                     strerror (errno));
  258.                 return (1);
  259.             }
  260.         } else
  261. #ifdef MSDOS
  262.         if (n > 0)
  263. #endif
  264.         {
  265.             len = PHLEN-PHEAD;
  266.             len = (msg[len] << 8) + msg[len+1];
  267.             if (len < 3 || len+PHSIZE != n) {
  268.                 ++STATS_NETERRD;
  269.                 continue;
  270.             }
  271.  
  272.             if (F(pack = packet_new (len, -1))) {
  273.                 ++STATS_NETERRD;
  274.                 continue;
  275.             }
  276.             memcpy (PHEAD, (char *)msg, n);
  277.             pack->netport = port->netport;
  278.             pack->length = len;
  279.             pack->address = PHFROM;        /* from */
  280.             packet_deliver (pack);
  281.             pack = 0;
  282.             continue;
  283.         }
  284.         break;
  285.     }
  286.  
  287.     return (0);
  288. }
  289.  
  290. struct NetDriver NEAR NetUdp = {
  291.     "UDP",
  292.     0,
  293.     NULL,    /* extra */
  294.     UdpInit,
  295.     UdpTerm,
  296.     UdpSend,
  297.     UdpReceive
  298. };
  299. #endif /* ifdef HAVE_UDP */
  300.